﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

namespace Pavilion.DesignerTool.ViewTools.ConnectableListBox
{
    public class ContainerNodeWrapper : NodeBaseWrapper, IConnectableItemContainer
    {
        private AnimationResourceData animationResource;

        public ContainerNode ContainerNode { get; set; }
        public NotifiableCollection<IConnectableItem> ConnectableItems { get; private set; }
        public NotifiableCollection<IConnectonator> Connectonators { get; private set; }

        public object Data
        {
            get { return ContainerNode; }
        }

        public ContainerNodeWrapper(ContainerNode containerNode, AnimationResourceData animationResource) : base(containerNode)
        {
            this.ContainerNode = containerNode;
            this.animationResource = animationResource;

            ConnectableItems = new NotifiableCollection<IConnectableItem>();
            Connectonators = new NotifiableCollection<IConnectonator>();

            foreach (NodeBase node in this.ContainerNode.NodeCollection)
                ConnectableItems.Add(CreateNodeBaseWrapper(node));

            foreach (NodeBaseWrapper nodeWrapper in ConnectableItems)
            {
                foreach (var link in nodeWrapper.Node.LinkCollection)
                    Connectonators.Add(CreateLinkWrapper(link, nodeWrapper));
            }
        }

        public NodeBaseWrapper AddNode(NodeBase node)
        {
            ContainerNode.AddNode(node);
            NodeBaseWrapper nodeWrapper = CreateNodeBaseWrapper(node);
            ConnectableItems.Add(nodeWrapper);

            return nodeWrapper;
        }

        public void RemoveNode(NodeBaseWrapper nodeWrapper)
        {
            ContainerNode.RemoveNode(nodeWrapper.Node.Name);
            ConnectableItems.Remove(nodeWrapper);
        }

        public void AddLink(NodeBaseWrapper startNode, NodeBaseWrapper endNode)
        {
            Link link = startNode.Node.AddLink(endNode.Node, null, OpenCriteria.Single);

            if (link != null)
                Connectonators.Add(CreateLinkWrapper(link, startNode, endNode));
        }

        private NodeBaseWrapper CreateNodeBaseWrapper(NodeBase node)
        {
            NodeBaseWrapper nodeWrapper = null;

            if (node is ContainerNode)
                nodeWrapper = new ContainerNodeWrapper(node as ContainerNode, animationResource);
            else if (node is AnimationNode)
                nodeWrapper = new AnimationNodeWrapper(node as AnimationNode, animationResource);
            else
                nodeWrapper = new NodeBaseWrapper(node);

            nodeWrapper.ParentContainerNodeWrapper = this;

            return nodeWrapper;
        }

        private LinkWrapper CreateLinkWrapper(Link link, IConnectableItem startingNode)
        {
            return CreateLinkWrapper(link, startingNode, ConnectableItems.First(x => (x as NodeBaseWrapper).Node == link.EndingNode));
        }

        private LinkWrapper CreateLinkWrapper(Link link, IConnectableItem startingNode, IConnectableItem endingNode)
        {
            LinkWrapper linkWrapper = new LinkWrapper(link, startingNode, endingNode);
            linkWrapper.Disposed += (item) => Connectonators.Remove(item);

            return linkWrapper;
        }

        internal IConnectableItem GetNode(string name)
        {
            return ConnectableItems.First((connectableItem) => connectableItem.Name == name);
        }
    }
}
